package org.ddl.core.interceptor;

import java.sql.Connection;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.ddl.core.context.ShardContext;
import org.ddl.core.entity.DataSourceTable;

/**
 * MyBatis拦截器，实现分表操作
 * 
 * @author yinjianwei
 * @date 2017年10月8日 上午11:23:55
 *
 */
@Intercepts({
		@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
public class MapperProxy implements Interceptor {

	private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
	private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
	private static final ReflectorFactory DEFAULT_REFLECTOR_FACTORY = new DefaultReflectorFactory();

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,
				DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
		// 分表前SQL
		String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
		DataSourceTable dataSourceTable = ShardContext.getCurrentDataSourceTableContext();
		// 逻辑表名
		String loaicTable = dataSourceTable.getLogicTable();
		// 真实表名
		String tableName = dataSourceTable.getTableName();
		// 替换SQL中的表名
		if (StringUtils.isNotBlank(originalSql) && StringUtils.isNotBlank(loaicTable)
				&& StringUtils.isNotBlank(tableName)) {
			// 分表后SQL
			String convertedSql = originalSql.replaceAll(loaicTable, tableName);
			metaStatementHandler.setValue("delegate.boundSql.sql", convertedSql);
		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
	}
}